home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume8 / jove / part06 < prev    next >
Encoding:
Internet Message Format  |  1987-02-02  |  58.7 KB

  1. Subject:  v08i025:  The JOVE text editor, Part06/13
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: seismo!rochester!jpayne (Jonathan Payne)
  6. Mod.sources: Volume 8, Issue 25
  7. Archive-name: jove/Part06
  8.  
  9. #! /bin/sh
  10. # This is a shell archive.  Remove anything before this line,
  11. # then unpack it by saving it in a file and typing "sh file".
  12. # If all goes well, you will see the message "End of archive 6 (of 13)."
  13. # Contents:  misc.c move.c paragraph.c portsrv.c proc.c re1.c table.h
  14. PATH=/bin:/usr/bin:/usr/ucb; export PATH
  15. echo shar: extracting "'misc.c'" '(7568 characters)'
  16. if test -f 'misc.c' ; then 
  17.   echo shar: will not over-write existing file "'misc.c'"
  18. else
  19. sed 's/^X//' >misc.c <<'@//E*O*F misc.c//'
  20. X/************************************************************************
  21. X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
  22. X * provided to you without charge, and with no warranty.  You may give  *
  23. X * away copies of JOVE, including sources, provided that this notice is *
  24. X * included in all the files.                                           *
  25. X ************************************************************************/
  26. X
  27. X#include "jove.h"
  28. X#include "ctype.h"
  29. X#include <signal.h>
  30. X#ifdef ANSICODES
  31. X#include "termcap.h"
  32. X#endif
  33. X
  34. XDigit()
  35. X{
  36. X    GetExp(LastKeyStruck);
  37. X}
  38. X
  39. XDigit0()
  40. X{
  41. X    GetExp('0');
  42. X}
  43. X
  44. XDigit1()
  45. X{
  46. X    GetExp('1');
  47. X}
  48. X
  49. XDigit2()
  50. X{
  51. X    GetExp('2');
  52. X}
  53. X
  54. XDigit3()
  55. X{
  56. X    GetExp('3');
  57. X}
  58. X
  59. XDigit4()
  60. X{
  61. X    GetExp('4');
  62. X}
  63. X
  64. XDigit5()
  65. X{
  66. X    GetExp('5');
  67. X}
  68. X
  69. XDigit6()
  70. X{
  71. X    GetExp('6');
  72. X}
  73. X
  74. XDigit7()
  75. X{
  76. X    GetExp('7');
  77. X}
  78. X
  79. XDigit8()
  80. X{
  81. X    GetExp('8');
  82. X}
  83. X
  84. XDigit9()
  85. X{
  86. X    GetExp('9');
  87. X}
  88. X
  89. XprCTIME()
  90. X{
  91. X    s_mess(": %f %s", get_time((time_t *) 0, (char *) 0, 0, -1));
  92. X}
  93. X
  94. Xextern int    alarmed;
  95. X
  96. XFourTime()
  97. X{
  98. X    int    oldc = LastKeyStruck,
  99. X        newc;
  100. X    int    nexp;
  101. X
  102. X    alarmed = 0;
  103. X    exp_p = YES;
  104. X    this_cmd = ARG_CMD;
  105. X    do {
  106. X        if ((nexp = exp * 4) != 0)
  107. X            exp = nexp;
  108. X        if (!alarmed)
  109. X            newc = waitchar();
  110. X        else
  111. X            newc = getch();
  112. X        if (alarmed)
  113. X            message(key_strokes);
  114. X    } while (newc == oldc);
  115. X    Ungetc(newc);
  116. X}
  117. X
  118. Xint    exp_p,
  119. X    exp;
  120. X
  121. XGetExp(c)
  122. X{
  123. X    int    sign = 0;
  124. X    static int    digited;
  125. X
  126. X    if (!isdigit(c) && c != '-')
  127. X        complain((char *) 0);
  128. X    if (exp_p == NO) {    /* if we just got here */
  129. X        exp = 0;    /* start over */
  130. X        digited = NO;
  131. X    } else if (exp_p == YES_NODIGIT) {
  132. X        sign = (exp < 0) ? -1 : 1;
  133. X        exp = 0;
  134. X    }
  135. X
  136. X    if (!sign)
  137. X        sign = (exp < 0) ? -1 : 1;
  138. X    if (sign == -1)
  139. X        exp = -exp;
  140. X    if (c == '-') {
  141. X        sign = -sign;
  142. X        goto goread;
  143. X    }
  144. X    for (;;) {
  145. X        if (alarmed)
  146. X            message(key_strokes);
  147. X        if (isdigit(c)) {
  148. X            exp = (exp * 10) + (c - '0');
  149. X            digited++;
  150. X        } else {
  151. X            if (digited)
  152. X                exp_p = YES;
  153. X            else {
  154. X                exp = 1;
  155. X                if (exp_p == NO)
  156. X                    exp_p = YES_NODIGIT;
  157. X            }
  158. X            exp *= sign;
  159. X            this_cmd = ARG_CMD;
  160. X            Ungetc(c);
  161. X            return;
  162. X        }
  163. Xgoread:        if (!alarmed)
  164. X            c = waitchar();
  165. X        else {
  166. X            add_mess(NullStr);
  167. X            c = getch();
  168. X        }
  169. X    }
  170. X}
  171. X
  172. XChrToOct()
  173. X{
  174. X    int    c;
  175. X
  176. X    c = waitchar();
  177. X    if (alarmed)
  178. X        message(key_strokes);
  179. X    ins_str(sprint("\\%03o", c), NO);
  180. X}
  181. X
  182. XStrLength()
  183. X{
  184. X    static char    inquotes[] = "Where are the quotes?";
  185. X    char    *first = StrIndex(-1, linebuf, curchar, '"'),
  186. X        *last = StrIndex(1, linebuf, curchar + 1, '"'),
  187. X        c;
  188. X    int    numchars = 0;
  189. X
  190. X    if (first == 0 || last == 0)
  191. X        complain(inquotes);
  192. X    first++;
  193. X    while (first < last) {
  194. X        c = *first++;
  195. X        if (c == '\\') {
  196. X            int    num;
  197. X
  198. X            if (!isdigit(*first))
  199. X                ++first;
  200. X            else {
  201. X                num = 3;
  202. X                while (num-- && isdigit(*first++) && first < last)
  203. X                    ;
  204. X            }
  205. X        }
  206. X        numchars++;
  207. X    }
  208. X    s_mess("%d characters", numchars);
  209. X}
  210. X
  211. X/* Transpos cur_char with cur_char - 1 */
  212. X
  213. XTransChar()
  214. X{
  215. X    char    before;
  216. X
  217. X    if (curchar == 0 || (eolp() && curchar == 1))
  218. X        complain((char *) 0);    /* BEEP */
  219. X    exp = 1;
  220. X    if (eolp())
  221. X        BackChar();
  222. X    before = linebuf[curchar - 1];
  223. X    DelPChar();
  224. X    ForChar();
  225. X    Insert(before);
  226. X}
  227. X
  228. X/* Switch current line with previous one */
  229. X
  230. XTransLines()
  231. X{
  232. X    disk_line    old_prev;
  233. X
  234. X    if (firstp(curline))
  235. X        return;
  236. X    exp = 1;
  237. X    lsave();
  238. X    old_prev = curline->l_prev->l_dline;
  239. X    curline->l_prev->l_dline = curline->l_dline;
  240. X    curline->l_dline = old_prev;
  241. X    getDOT();
  242. X    if (!lastp(curline))
  243. X        line_move(FORWARD, NO);
  244. X    modify();
  245. X}
  246. X
  247. XLeave()
  248. X{
  249. X    longjmp(mainjmp, QUIT);
  250. X}
  251. X
  252. X/* If argument is specified, kill that many lines down.  Otherwise,
  253. X   if we "appear" to be at the end of a line, i.e. everything to the
  254. X   right of the cursor is white space, we delete the line separator
  255. X   as if we were at the end of the line. */
  256. X
  257. XKillEOL()
  258. X{
  259. X    Line    *line2;
  260. X    int    char2;
  261. X
  262. X    if (exp_p) {
  263. X        if (exp == 0) {    /* Kill to beginning of line */
  264. X            line2 = curline;
  265. X            char2 = 0;
  266. X        } else {
  267. X            line2 = next_line(curline, exp);
  268. X            if ((LineDist(curline, line2) < exp) || (line2 == curline))
  269. X                char2 = length(line2);
  270. X            else
  271. X                char2 = 0;
  272. X        }
  273. X    } else if (blnkp(&linebuf[curchar])) {
  274. X        line2 = next_line(curline, 1);
  275. X        if (line2 == curline)
  276. X            char2 = length(curline);
  277. X        else
  278. X            char2 = 0;
  279. X    } else {
  280. X        line2 = curline;
  281. X        char2 = length(curline);
  282. X    }
  283. X    reg_kill(line2, char2, 0);
  284. X}
  285. X
  286. X/* Kill to beginning of sentence */
  287. X
  288. XKillBos()
  289. X{
  290. X    exp = -exp;
  291. X    KillEos();
  292. X}
  293. X
  294. X/* Kill to end of sentence */
  295. X
  296. XKillEos()
  297. X{
  298. X    Line    *line1;
  299. X    int    char1;
  300. X
  301. X    line1 = curline;
  302. X    char1 = curchar;
  303. X    Eos();
  304. X    reg_kill(line1, char1, 1);
  305. X}
  306. X
  307. XKillExpr()
  308. X{
  309. X    Line    *line1;
  310. X    int    char1;
  311. X
  312. X    line1 = curline;
  313. X    char1 = curchar;
  314. X    FSexpr();
  315. X    reg_kill(line1, char1, 1);
  316. X}
  317. X
  318. XEscPrefix()
  319. X{
  320. X    HandlePref(pref1map);
  321. X}
  322. X
  323. XCtlxPrefix()
  324. X{
  325. X    HandlePref(pref2map);
  326. X}
  327. X
  328. XMiscPrefix()
  329. X{
  330. X    HandlePref(miscmap);
  331. X}
  332. X
  333. XHandlePref(map)
  334. Xdata_obj    **map;
  335. X{
  336. X    register data_obj    *cp;
  337. X    register int    c;
  338. X
  339. X    c = waitchar();
  340. X    if (c == CTL(G)) {
  341. X        message("[Aborted]");
  342. X        rbell();
  343. X        return;
  344. X    }
  345. X
  346. X    if (alarmed)
  347. X        message(key_strokes);
  348. X
  349. X    cp = map[c];
  350. X    if (cp == 0) {
  351. X        s_mess("[%sunbound]", key_strokes);
  352. X        rbell();
  353. X    } else
  354. X        ExecCmd(cp);
  355. X}
  356. X
  357. XYank()
  358. X{
  359. X    Line    *line,
  360. X        *lp;
  361. X    Bufpos    *dot;
  362. X
  363. X    if (killbuf[killptr] == 0)
  364. X        complain("[Nothing to yank!]");
  365. X    lsave();
  366. X    this_cmd = YANKCMD;
  367. X    line = killbuf[killptr];
  368. X    lp = lastline(line);
  369. X    dot = DoYank(line, 0, lp, length(lp), curline, curchar, curbuf);
  370. X    SetMark();
  371. X    SetDot(dot);
  372. X}
  373. X
  374. XWtModBuf()
  375. X{
  376. X    if (!ModBufs(NO))
  377. X        message("[No buffers need saving]");
  378. X    else
  379. X        put_bufs(exp_p);
  380. X}
  381. X
  382. Xput_bufs(askp)
  383. X{
  384. X    register Buffer    *oldb = curbuf,    
  385. X            *b;        
  386. X
  387. X    for (b = world; b != 0; b = b->b_next) {
  388. X        if (!IsModified(b) || b->b_type != B_FILE)
  389. X            continue;
  390. X        SetBuf(b);    /* Make this current Buffer */
  391. X        if (curbuf->b_fname == 0) {
  392. X            char    *newname;
  393. X
  394. X            newname = ask(NullStr, "Buffer \"%s\" needs a file name; type Return to skip: ", b->b_name);
  395. X            if (*newname == 0)
  396. X                continue;
  397. X            setfname(b, newname);
  398. X        }
  399. X        if (askp && (yes_or_no_p("Write %s? ", curbuf->b_fname) == NO))
  400. X            continue;
  401. X        filemunge(curbuf->b_fname);
  402. X        chk_mtime(curbuf, curbuf->b_fname, "save");
  403. X        file_write(curbuf->b_fname, 0);
  404. X        unmodify();
  405. X    }
  406. X    SetBuf(oldb);
  407. X}
  408. X
  409. XToIndent()
  410. X{
  411. X    register char    *cp,
  412. X            c;
  413. X
  414. X    for (cp = linebuf; c = *cp; cp++)
  415. X        if (c != ' ' && c != '\t')
  416. X            break;
  417. X    curchar = cp - linebuf;
  418. X}
  419. X
  420. XGoLine()
  421. X{
  422. X    Line    *newline;
  423. X
  424. X#ifndef ANSICODES
  425. X    if (exp_p == NO)
  426. X        return;
  427. X#else
  428. X    if (exp_p == NO || exp <= 0) {
  429. X        if (SP)
  430. X            putpad(SP, 1);    /* Ask for cursor position */
  431. X        return;
  432. X    }
  433. X#endif
  434. X    newline = next_line(curbuf->b_first, exp - 1);
  435. X    PushPntp(newline);
  436. X    SetLine(newline);
  437. X}
  438. X
  439. X#ifdef ANSICODES
  440. XMoveToCursor(line, col)
  441. X{
  442. X    register struct scrimage *sp = &PhysScreen[line];
  443. X
  444. X    while (sp->s_id == NULL)
  445. X        sp = &PhysScreen[--line];
  446. X    if (sp->s_flags & MODELINE)
  447. X        complain((char *) 0);
  448. X    if (curwind != sp->s_window)
  449. X        SetWind(sp->s_window);
  450. X    SetLine(sp->s_lp);
  451. X    curchar = how_far(sp->s_lp, col);
  452. X}
  453. X
  454. XAnsiCodes()
  455. X{
  456. X    int    c;
  457. X    int    num1 = 0;
  458. X    int    num2;
  459. X    static char *unsupported = "[Unsupported ANSI code received]";
  460. X
  461. X    while (isdigit(c = getch()))
  462. X        num1 = (num1*10) + (c - '0');
  463. X
  464. X    switch (c) {
  465. X    case ';':
  466. X        num2 = 0;
  467. X        while (isdigit(c = getch()))
  468. X            num2 = (num2*10) + (c - '0');
  469. X        switch (c) {
  470. X        case 'R':
  471. X            MoveToCursor(--num1, --num2);
  472. X            break;
  473. X        case 'H':
  474. X            Eow(); Bol();
  475. X            break;
  476. X        default:
  477. X            complain(unsupported);
  478. X        }
  479. X        break;
  480. X    case 'A':
  481. X        line_move(BACKWARD, YES);
  482. X        break;
  483. X    case 'B':
  484. X        line_move(FORWARD, YES);
  485. X        break;
  486. X    case 'C':
  487. X        ForChar();
  488. X        break;
  489. X    case 'D':
  490. X        BackChar();
  491. X        break;
  492. X    case 'H':
  493. X        Bow();
  494. X        break;
  495. X    case 'J':
  496. X        if (num1 == 2) {
  497. X            ClAndRedraw();
  498. X            break;
  499. X        }
  500. X        /* FALL THROUGH */
  501. X    default:
  502. X        complain(unsupported);
  503. X    }
  504. X}
  505. X#endif ANSICODES
  506. X
  507. XNotModified()
  508. X{
  509. X    unmodify();
  510. X}
  511. X
  512. XSetLMargin()
  513. X{
  514. X    LMargin = calc_pos(linebuf, curchar);
  515. X}
  516. X
  517. XSetRMargin()
  518. X{
  519. X    RMargin = calc_pos(linebuf, curchar);
  520. X}
  521. @//E*O*F misc.c//
  522. if test 7568 -ne "`wc -c <'misc.c'`"; then
  523.     echo shar: error transmitting "'misc.c'" '(should have been 7568 characters)'
  524. fi
  525. fi # end of overwriting check
  526. echo shar: extracting "'move.c'" '(4397 characters)'
  527. if test -f 'move.c' ; then 
  528.   echo shar: will not over-write existing file "'move.c'"
  529. else
  530. sed 's/^X//' >move.c <<'@//E*O*F move.c//'
  531. X/************************************************************************
  532. X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
  533. X * provided to you without charge, and with no warranty.  You may give  *
  534. X * away copies of JOVE, including sources, provided that this notice is *
  535. X * included in all the files.                                           *
  536. X ************************************************************************/
  537. X
  538. X#include "jove.h"
  539. X#include "ctype.h"
  540. X
  541. Xstatic int    line_pos;
  542. X
  543. XForChar()
  544. X{
  545. X    register int    num = exp;
  546. X
  547. X    if (exp < 0) {
  548. X        exp = -exp;
  549. X        BackChar();
  550. X        return;
  551. X    }
  552. X    exp = 1;
  553. X    while (--num >= 0) {
  554. X        if (eolp()) {            /* Go to the next Line */
  555. X            if (curline->l_next == 0)
  556. X                break;
  557. X            SetLine(curline->l_next);
  558. X        } else
  559. X            curchar++;
  560. X    }
  561. X}
  562. X
  563. XBackChar()
  564. X{
  565. X    register int    num = exp;
  566. X
  567. X    if (exp < 0) {
  568. X        exp = -exp;
  569. X        ForChar();
  570. X        return;
  571. X    }
  572. X    exp = 1;
  573. X    while (--num >= 0) {
  574. X        if (bolp()) {
  575. X            if (curline->l_prev == 0)
  576. X                break;
  577. X            SetLine(curline->l_prev);
  578. X            Eol();
  579. X        } else
  580. X            --curchar;
  581. X    }
  582. X}
  583. X
  584. XNextLine()
  585. X{
  586. X    if ((curline == curbuf->b_last) && eolp())
  587. X        complain(NullStr);
  588. X    line_move(FORWARD, YES);
  589. X}
  590. X
  591. XPrevLine()
  592. X{
  593. X    if ((curline == curbuf->b_first) && bolp())
  594. X        complain(NullStr);
  595. X    line_move(BACKWARD, YES);
  596. X}
  597. X
  598. X/* moves to a different line in DIR; LINE_CMD says whether this is
  599. X   being called from NextLine() or PrevLine(), in which case it tries
  600. X   to line up the column with the column of the current line */
  601. X
  602. Xline_move(dir, line_cmd)
  603. X{
  604. X    Line    *(*proc)() = (dir == FORWARD) ? next_line : prev_line;
  605. X    Line    *line;
  606. X
  607. X    line = (*proc)(curline, exp);
  608. X    if (line == curline) {
  609. X        (dir == FORWARD) ? Eol() : Bol();
  610. X        return;
  611. X    }
  612. X
  613. X    if (line_cmd) {
  614. X        this_cmd = LINECMD;
  615. X        if (last_cmd != LINECMD)
  616. X            line_pos = calc_pos(linebuf, curchar);
  617. X    }
  618. X    SetLine(line);        /* curline is in linebuf now */
  619. X    if (line_cmd)
  620. X        curchar = how_far(curline, line_pos);
  621. X}
  622. X
  623. X/* returns what cur_char should be for that position col */
  624. X
  625. Xhow_far(line, col)
  626. XLine    *line;
  627. X{
  628. X    register char    *lp;
  629. X    register int    pos,
  630. X            c;
  631. X    char    *base;
  632. X
  633. X    base = lp = lcontents(line);
  634. X    pos = 0;
  635. X
  636. X    while (pos < col && (c = (*lp & 0177))) {
  637. X        if (c == '\t')
  638. X            pos += (tabstop - (pos % tabstop));
  639. X        else if (isctrl(c))
  640. X            pos += 2;
  641. X        else
  642. X            pos++;
  643. X        lp++;
  644. X    }
  645. X
  646. X    return lp - base;
  647. X}
  648. X
  649. XBol()
  650. X{
  651. X    curchar = 0;
  652. X}
  653. X
  654. XEol()
  655. X{
  656. X    curchar = strlen(linebuf);
  657. X}
  658. X
  659. XEof()
  660. X{
  661. X    PushPntp(curbuf->b_last);
  662. X    ToLast();
  663. X}
  664. X
  665. XBof()
  666. X{
  667. X    PushPntp(curbuf->b_first);
  668. X    ToFirst();
  669. X}
  670. X
  671. X/* Move forward (if dir > 0) or backward (if dir < 0) a sentence.  Deals
  672. X   with all the kludgery involved with paragraphs, and moving backwards
  673. X   is particularly yucky. */
  674. X
  675. Xto_sent(dir)
  676. X{
  677. X    Bufpos    *new,
  678. X        old;
  679. X    extern char    *ParaStr;
  680. X
  681. X    DOTsave(&old);
  682. X
  683. X    new = dosearch("^[ \t]*$\\|[?.!]", dir, 1);
  684. X    if (new == 0) {
  685. X        (dir < 0) ? ToFirst() : ToLast();
  686. X        return;
  687. X    }
  688. X    SetDot(new);
  689. X    if (dir < 0) {
  690. X        to_word(1);
  691. X        if ((old.p_line == curline && old.p_char <= curchar) ||
  692. X            (inorder(new->p_line, new->p_char, old.p_line, old.p_char) &&
  693. X             inorder(old.p_line, old.p_char, curline, curchar))) {
  694. X                 SetDot(new);
  695. X                 to_sent(dir);
  696. X        }
  697. X        return;        /* We're there? */
  698. X    }
  699. X    if (blnkp(linebuf)) {
  700. X        Bol();
  701. X        BackChar();
  702. X        if (old.p_line == curline && old.p_char >= curchar) {
  703. X            to_word(1);    /* Oh brother this is painful */
  704. X            to_sent(1);
  705. X        }
  706. X    } else {
  707. X        extern int    REbom;
  708. X
  709. X        curchar = REbom + 1;    /* Just after the [?.!] */
  710. X        if (LookingAt("[\")]  *\\|[\")]$", linebuf, curchar))
  711. X            curchar++;
  712. X        else if (!eolp() && !LookingAt("  *", linebuf, curchar))
  713. X            to_sent(dir);
  714. X    }
  715. X}
  716. X
  717. XBos()
  718. X{
  719. X    int    num = exp;
  720. X
  721. X    if (exp < 0) {
  722. X        exp = -exp;
  723. X        Eos();
  724. X        return;
  725. X    }
  726. X
  727. X    exp = 1;
  728. X
  729. X    while (--num >= 0) {
  730. X        to_sent(-1);
  731. X        if (bobp())
  732. X            break;
  733. X    }
  734. X}
  735. X
  736. XEos()
  737. X{
  738. X    int    num = exp;
  739. X
  740. X    if (exp < 0) {
  741. X        exp = -exp;
  742. X        Bos();
  743. X        return;
  744. X    }
  745. X
  746. X    exp = 1;
  747. X
  748. X    while (--num >= 0) {
  749. X        to_sent(1);
  750. X        if (eobp())
  751. X            break;
  752. X    }
  753. X}
  754. X
  755. XForWord()
  756. X{
  757. X    register char    c;
  758. X    register int    num = exp;
  759. X
  760. X    if (exp < 0) {
  761. X        exp = -exp;
  762. X        BackWord();
  763. X        return;
  764. X    }
  765. X    exp = 1;
  766. X    while (--num >= 0) {
  767. X        to_word(1);
  768. X        while ((c = linebuf[curchar]) != 0 && isword(c))
  769. X            curchar++;
  770. X        if (eobp())
  771. X            break;
  772. X    }
  773. X    this_cmd = 0;    /* Semi kludge to stop some unfavorable behavior */
  774. X}
  775. X
  776. XBackWord()
  777. X{
  778. X    register int    num = exp;
  779. X    register char    c;
  780. X
  781. X    if (exp < 0) {
  782. X        exp = -exp;
  783. X        ForWord();
  784. X        return;
  785. X    }
  786. X    exp = 1;
  787. X    while (--num >= 0) {
  788. X        to_word(-1);
  789. X        while (!bolp() && (c = linebuf[curchar - 1], isword(c)))
  790. X            --curchar;
  791. X        if (bobp())
  792. X            break;
  793. X    }
  794. X    this_cmd = 0;
  795. X}
  796. @//E*O*F move.c//
  797. if test 4397 -ne "`wc -c <'move.c'`"; then
  798.     echo shar: error transmitting "'move.c'" '(should have been 4397 characters)'
  799. fi
  800. fi # end of overwriting check
  801. echo shar: extracting "'paragraph.c'" '(13888 characters)'
  802. if test -f 'paragraph.c' ; then 
  803.   echo shar: will not over-write existing file "'paragraph.c'"
  804. else
  805. sed 's/^X//' >paragraph.c <<'@//E*O*F paragraph.c//'
  806. X/************************************************************************
  807. X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
  808. X * provided to you without charge, and with no warranty.  You may give  *
  809. X * away copies of JOVE, including sources, provided that this notice is *
  810. X * included in all the files.                                           *
  811. X ************************************************************************/
  812. X
  813. X#include "jove.h"
  814. X
  815. X/* Thanks to Brian Harvey for this paragraph boundery finding algorithm.
  816. X   It's really quite hairy figuring it out.  This deals with paragraphs that
  817. X   are seperated by blank lines, lines beginning with a Period (assumed to
  818. X   be an nroff command), lines beginning with BackSlash (assumed to be Tex
  819. X   commands).  Also handles paragraphs that are separated by lines of
  820. X   different indent; and it deals with outdented paragraphs, too.  It's
  821. X   really quite nice.  Here's Brian's algorithm.
  822. X
  823. X   Definitions:
  824. X   
  825. X   THIS means the line containing the cursor.
  826. X   PREV means the line above THIS.
  827. X   NEXT means the line below THIS.
  828. X   
  829. X   BLANK means empty, empty except for spaces and tabs, starts with a period
  830. X   or a backslash, or nonexistent (because the edge of the buffer is
  831. X   reached).  ((BH 12/24/85 A line starting with backslash is blank only if
  832. X   the following line also starts with backslash.  This is so that \noindent
  833. X   is part of a paragraph, but long strings of TeX commands don't get
  834. X   rearranged.  It still isn't perfect but it's better.))
  835. X
  836. X   BSBLANK means BLANK or starts with a backslash.  (BH 12/24/85)
  837. X   
  838. X   HEAD means the first (nonblank) line of the paragraph containing THIS.
  839. X   BODY means all other (nonblank) lines of the paragraph.
  840. X   TAIL means the last (nb) line of the paragraph.  (TAIL is part of BODY.)
  841. X   
  842. X   HEAD INDENT means the indentation of HEAD.  M-J should preserve this.
  843. X   BODY INDENT means the indentation of BODY.  Ditto.
  844. X   
  845. X   Subprocedures:
  846. X   
  847. X   TAILRULE(BODYLINE)
  848. X   If BODYLINE is BLANK, the paragraph has only one line, and there is no
  849. X   BODY and therefore no TAIL.  Return.  Otherwise, starting from BODYLINE,
  850. X   move down until you find a line that either is BSBLANK or has a different
  851. X   indentation from BODYLINE.  The line above that different line is TAIL.
  852. X   Return.
  853. X   
  854. X   Rules:
  855. X   
  856. X   1.  If THIS is BLANK, which command are you doing?  If M-J or M-[, then go
  857. X   up to the first non-BLANK line and start over.  (If there is no non-BLANK
  858. X   line before THIS, ring the bell.)  If M-], then the first non-BLANK line
  859. X   below THIS is HEAD, and the second consecutive non-BSBLANK line (if any) is
  860. X   the beginning of BODY.  (If there is no non-BLANK line after THIS, ring
  861. X   the bell.)  Do TAILRULE(beginning-of-BODY).  Go to rule A.
  862. X
  863. X   2.  If PREV is BLANK or THIS is BSBLANK, then THIS is HEAD, and NEXT (if
  864. X   not BSBLANK) is in BODY.  Do TAILRULE(NEXT).  Go to rule A.
  865. X
  866. X   3.  If NEXT is BSBLANK, then THIS is TAIL, therefore part of BODY.  Go to
  867. X   rule 5 to find HEAD.
  868. X   
  869. X   4.  If either NEXT or PREV has the same indentation as THIS, then THIS is
  870. X   part of BODY.  Do TAILRULE(THIS).  Go to rule 5 to find HEAD.  Otherwise,
  871. X   go to rule 6.
  872. X   
  873. X   5.  Go up until you find a line that is either BSBLANK or has a different
  874. X   indentation from THIS.  If that line is BLANK, the line below it is HEAD.
  875. X   If that line is non-BLANK, then call that new line THIS for what follows.
  876. X   If (the new) PREV has the same indent as THIS, then (the new) NEXT is
  877. X   HEAD.  If PREV has a different indent from THIS, then THIS is HEAD.  Go to
  878. X   rule A.
  879. X   
  880. X   6.  If you got here, then both NEXT and PREV are nonblank and are
  881. X   differently indented from THIS.  This is a tricky case and there is no
  882. X   guarantee that you're going to win.  The most straightforward thing to do
  883. X   is assume that we are not using hanging indentation.  In that case:
  884. X   whichever of PREV and THIS is indented further is HEAD.  Do
  885. X   TAILRULE(HEAD+1).  Go to rule A.
  886. X   
  887. X   6+.  A more complicated variant would be this: if THIS is indented further
  888. X   than PREV, we are using regular indentation and rule 6 applies.  If PREV
  889. X   is indented further than THIS, look at both NEXT and the line after NEXT.
  890. X   If those two lines are indented equally, and more than THIS, then we are
  891. X   using hanging indent, THIS is HEAD, and NEXT is the first line of BODY.
  892. X   Do TAILRULE(NEXT).  Otherwise, rule 6 applies.
  893. X   
  894. X   A.  You now know where HEAD and TAIL are.  The indentation of HEAD is HEAD
  895. X   INDENT; the indentation of TAIL is BODY INDENT.
  896. X   
  897. X   B.  If you are trying to M-J, you are now ready to do it.
  898. X   
  899. X   C.  If you are trying to M-], leave point after the newline that ends
  900. X   TAIL.  In other words, leave the cursor at the beginning of the line
  901. X   after TAIL.  It is not possible for this to leave point where it started
  902. X   unless it was already at the end of the buffer.
  903. X   
  904. X   D.  If you are trying to M-[, if the line before HEAD is not BLANK, then
  905. X   leave point just before HEAD.  That is, leave the cursor at the beginning
  906. X   of HEAD.  If the line before HEAD is BLANK, then leave the cursor at the
  907. X   beginning of that line.  If the cursor didn't move, go up to the first
  908. X   earlier non-BLANK line and start over.
  909. X
  910. X
  911. X   End of Algorithm.  I implemented rule 6+ because it seemed nicer.  */
  912. X
  913. Xint    RMargin = 78,
  914. X    LMargin = 0;
  915. XLine    *para_head,
  916. X    *para_tail;
  917. Xint    head_indent,
  918. X    body_indent;
  919. Xstatic int    use_lmargin;
  920. X
  921. X/* some defines for paragraph boundery checking */
  922. X#define I_EMPTY        -1    /* line "looks" empty (spaces and tabs) */
  923. X#define I_PERIOD    -2    /* line begins with "." or "\" */
  924. X#define I_BUFEDGE    -3    /* line is nonexistent (edge of buffer) */
  925. X
  926. Xstatic int    bslash;        /* Nonzero if get_indent finds line starting
  927. X                   with backslash */
  928. X
  929. Xi_bsblank(lp)
  930. XLine    *lp;
  931. X{
  932. X    if (i_blank(lp))
  933. X        return 1;
  934. X    return bslash;
  935. X}
  936. X
  937. Xi_blank(lp)
  938. XLine    *lp;
  939. X{
  940. X    return (get_indent(lp) < 0);
  941. X}
  942. X
  943. Xstatic 
  944. Xget_indent(lp)
  945. Xregister Line    *lp;
  946. X{
  947. X    Bufpos    save;
  948. X    register int    indent;
  949. X
  950. X    bslash = 0;
  951. X    if (lp == 0)
  952. X        return I_BUFEDGE;
  953. X    DOTsave(&save);
  954. X    SetLine(lp);
  955. X    if (blnkp(linebuf))
  956. X        indent = I_EMPTY;
  957. X     else if (linebuf[0] == '.')
  958. X        indent = I_PERIOD;
  959. X    else if (linebuf[0] == '\\') {
  960. X        /* BH 12/24/85.  Backslash is BLANK only if next line
  961. X           also starts with Backslash. */
  962. X        bslash++;
  963. X        SetLine(lp->l_next);
  964. X        if (linebuf[0] == '\\')
  965. X            indent = I_PERIOD;
  966. X        else
  967. X            indent = 0;
  968. X    } else {
  969. X        ToIndent();
  970. X        indent = calc_pos(linebuf, curchar);
  971. X    }
  972. X    SetDot(&save);
  973. X
  974. X    return indent;
  975. X}
  976. X
  977. Xstatic Line *
  978. Xtailrule(lp)
  979. Xregister Line    *lp;
  980. X{
  981. X    int    i;
  982. X
  983. X    i = get_indent(lp);
  984. X    if (i < 0)
  985. X        return lp;    /* one line paragraph */
  986. X    do {
  987. X        if ((get_indent(lp->l_next) != i) || bslash)
  988. X            /* BH line with backslash is head of next para */
  989. X            break;
  990. X    } while ((lp = lp->l_next) != 0);
  991. X    if (lp == 0)
  992. X        complain((char *) 0);
  993. X    return lp;
  994. X}
  995. X
  996. X/* Finds the beginning, end and indent of the current paragraph, and sets
  997. X   the above global variables.  HOW says how to behave when we're between
  998. X   paragraphs.  That is, it's either FORWARD or BACKWARD depending on which
  999. X   way we're favoring. */
  1000. X
  1001. Xfind_para(how)
  1002. X{
  1003. X    Line    *this,
  1004. X        *prev,
  1005. X        *next,
  1006. X        *head = 0,
  1007. X        *body = 0,
  1008. X        *tail = 0;
  1009. X    int    this_indent;
  1010. X    Bufpos    orig;        /* remember where we were when we started */
  1011. X
  1012. X    exp = 1;
  1013. X    DOTsave(&orig);
  1014. Xstrt:
  1015. X    this = curline;
  1016. X    prev = curline->l_prev;
  1017. X    next = curline->l_next;
  1018. X    this_indent = get_indent(this);
  1019. X
  1020. X    if (i_blank(this)) {        /* rule 1 */
  1021. X        if (how == BACKWARD) {
  1022. X            while (i_blank(curline))
  1023. X                if (firstp(curline))
  1024. X                    complain((char *) 0);
  1025. X                else
  1026. X                    line_move(BACKWARD, NO);
  1027. X            goto strt;
  1028. X        } else {
  1029. X            while (i_blank(curline))
  1030. X                if (lastp(curline))
  1031. X                    complain((char *) 0);
  1032. X                else
  1033. X                    line_move(FORWARD, NO);
  1034. X            head = curline;
  1035. X            next = curline->l_next;
  1036. X            if (!i_bsblank(next))
  1037. X                body = next;
  1038. X            else
  1039. X                body = head;
  1040. X        }
  1041. X    } else if (i_bsblank(this) || i_blank(prev)) {    /* rule 2 */
  1042. X        head = this;
  1043. X        if (!i_bsblank(next))
  1044. X            body = next;
  1045. X    } else if (i_bsblank(next)) {    /* rule 3 */
  1046. X        tail = this;
  1047. X        body = this;
  1048. X    } else if ((get_indent(next) == this_indent) ||    /* rule 4 */
  1049. X           (get_indent(prev) == this_indent))
  1050. X        body = this;
  1051. X    else {        /* rule 6+ */
  1052. X        if (get_indent(prev) > this_indent) {
  1053. X            /* hanging indent maybe? */
  1054. X            if ((next != 0) &&
  1055. X                (get_indent(next) == get_indent(next->l_next))) {
  1056. X                head = this;
  1057. X                body = next;
  1058. X            }
  1059. X        }
  1060. X        /* Now we handle hanging indent else and the other
  1061. X           case of this_indent > get_indent(prev).  That is,
  1062. X           if we didn't resolve HEAD in the above if, then
  1063. X           we are not a hanging indent. */
  1064. X        if (head == 0) {    /* still don't know */
  1065. X            if (this_indent > get_indent(prev))
  1066. X                head = this;
  1067. X            else
  1068. X                head = prev;
  1069. X            body = head->l_next;
  1070. X        }
  1071. X    }
  1072. X    /* rule 5 -- find the missing parts */
  1073. X    if (head == 0) {    /* haven't found head of paragraph so do so now */
  1074. X        Line    *lp;
  1075. X        int    i;
  1076. X
  1077. X        lp = this;
  1078. X        do {
  1079. X            i = get_indent(lp->l_prev);
  1080. X            if (i < 0)    /* is blank */
  1081. X                head = lp;
  1082. X            else if (i != this_indent || bslash) {
  1083. X                Line    *this = lp->l_prev;
  1084. X
  1085. X                if (get_indent(this->l_prev) == i)
  1086. X                    head = this->l_next;
  1087. X                else
  1088. X                    head = this;
  1089. X            }
  1090. X        } while (head == 0 && (lp = lp->l_prev) != 0);
  1091. X        if (lp == 0)
  1092. X            complain((char *) 0);
  1093. X    }
  1094. X    if (body == 0)        /* this must be a one line paragraph */
  1095. X        body = head;
  1096. X    if (tail == 0)
  1097. X        tail = tailrule(body);
  1098. X    if (tail == 0 || head == 0 || body == 0)
  1099. X        complain("BUG! tail(%d),head(%d),body(%d)!", tail, head, body);
  1100. X    para_head = head;
  1101. X    para_tail = tail;
  1102. X    head_indent = get_indent(head);
  1103. X    body_indent = get_indent(body);
  1104. X
  1105. X    SetDot(&orig);
  1106. X}
  1107. X
  1108. XJustify()
  1109. X{
  1110. X    use_lmargin = (exp_p != NO);
  1111. X    find_para(BACKWARD);
  1112. X    DoJustify(para_head, 0, para_tail, length(para_tail), NO,
  1113. X          use_lmargin ? LMargin : body_indent);
  1114. X}
  1115. X
  1116. XLine *
  1117. Xmax_line(l1, l2)
  1118. XLine    *l1,
  1119. X    *l2;
  1120. X{
  1121. X    if (inorder(l1, 0, l2, 0))
  1122. X        return l2;
  1123. X    return l1;
  1124. X}
  1125. X
  1126. XLine *
  1127. Xmin_line(l1, l2)
  1128. XLine    *l1,
  1129. X    *l2;
  1130. X{
  1131. X    if (inorder(l1, 0, l2, 0))
  1132. X        return l1;
  1133. X    return l2;
  1134. X}
  1135. X
  1136. XRegJustify()
  1137. X{
  1138. X    Mark    *mp = CurMark(),
  1139. X        *tailmark;
  1140. X    Line    *l1 = curline,
  1141. X        *l2 = mp->m_line;
  1142. X    int    c1 = curchar,
  1143. X        c2 = mp->m_char;
  1144. X    Line    *rl1,
  1145. X        *rl2;
  1146. X
  1147. X    use_lmargin = (exp_p != NO);
  1148. X    (void) fixorder(&l1, &c1, &l2, &c2);
  1149. X    do {
  1150. X        DotTo(l1, c1);
  1151. X        find_para(FORWARD);
  1152. X        rl1 = max_line(l1, para_head);
  1153. X        rl2 = min_line(l2, para_tail);
  1154. X        tailmark = MakeMark(para_tail, 0, FLOATER);
  1155. X        DoJustify(rl1, (rl1 == l1) ? c1 : 0, rl2,
  1156. X              (rl2 == l2) ? c2 : length(rl2),
  1157. X              NO, use_lmargin ? LMargin : body_indent);
  1158. X        l1 = tailmark->m_line->l_next;
  1159. X        DelMark(tailmark);
  1160. X        c1 = 0;
  1161. X    } while (l1 != 0 && l2 != rl2);
  1162. X}
  1163. X
  1164. Xdo_rfill()
  1165. X{
  1166. X    Mark    *mp = CurMark();
  1167. X    Line    *l1 = curline,
  1168. X        *l2 = mp->m_line;
  1169. X    int    c1 = curchar,
  1170. X        c2 = mp->m_char;
  1171. X
  1172. X    use_lmargin = (exp_p != NO);
  1173. X    (void) fixorder(&l1, &c1, &l2, &c2);
  1174. X    DoJustify(l1, c1, l2, c2, NO, use_lmargin ? LMargin : 0);
  1175. X}
  1176. X
  1177. Xdo_space()
  1178. X{
  1179. X    int    c1 = curchar,
  1180. X        c2 = c1,
  1181. X        diff,
  1182. X        nspace;
  1183. X    char    ch;
  1184. X
  1185. X    while (c1 > 0 && ((ch = linebuf[c1 - 1]) == ' ' || ch == '\t'))
  1186. X        c1--;
  1187. X    while ((ch = linebuf[c2]) == ' ' || ch == '\t')
  1188. X        c2++;
  1189. X    diff = (c2 - c1);
  1190. X    curchar = c2;
  1191. X
  1192. X    if (diff == 0)
  1193. X        return;
  1194. X    if (c1 > 0) {
  1195. X        int    topunct = c1 - 1;
  1196. X
  1197. X        nspace = 1;
  1198. X        if (diff >= 2) {
  1199. X            while (index("\")]", linebuf[topunct])) {
  1200. X                if (topunct == 0)
  1201. X                    break;
  1202. X                topunct--;
  1203. X            }
  1204. X            if (index("?!.:", linebuf[topunct]))
  1205. X                nspace = 2;
  1206. X        }
  1207. X    } else
  1208. X        nspace = 0;
  1209. X
  1210. X    if (diff > nspace)
  1211. X        DoTimes(DelPChar(), (diff - nspace));
  1212. X    else if (diff < nspace)
  1213. X        DoTimes(Insert(' '), (nspace - diff));
  1214. X}
  1215. X
  1216. XDoJustify(l1, c1, l2, c2, scrunch, indent)
  1217. XLine    *l1,
  1218. X    *l2;
  1219. X{
  1220. X    int    okay_char = -1;
  1221. X    char    *cp;
  1222. X    Mark    *savedot = MakeMark(curline, curchar, FLOATER),
  1223. X        *endmark;
  1224. X
  1225. X    exp = 1;
  1226. X    (void) fixorder(&l1, &c1, &l2, &c2);    /* l1/c1 will be before l2/c2 */
  1227. X    DotTo(l1, c1);
  1228. X    if (get_indent(l1) >= c1) {
  1229. X        if (use_lmargin) {
  1230. X            n_indent(indent + (head_indent - body_indent));
  1231. X            use_lmargin = 0;    /* turn this off now */
  1232. X        }
  1233. X        ToIndent();
  1234. X    }
  1235. X    endmark = MakeMark(l2, c2, FLOATER);
  1236. X
  1237. X    for (;;) {
  1238. X        cp = StrIndex(1, linebuf, curchar, ' ');
  1239. X        if (cp == 0)
  1240. X            Eol();
  1241. X        else
  1242. X            curchar = (cp - linebuf);
  1243. X        if (curline == endmark->m_line && curchar >= endmark->m_char)
  1244. X            goto outahere;
  1245. X        if (eolp()) {
  1246. X            ins_str("  ", NO);
  1247. X            DelNChar();    /* delete line separator */
  1248. X            curchar -= 2;    /* back over the spaces */
  1249. X        }
  1250. X        /* at this point we are ALWAYS sitting right after
  1251. X           a word - that is, just before some spaces or the
  1252. X           end of the line */
  1253. X        if (calc_pos(linebuf, curchar) <= RMargin) {
  1254. X            okay_char = curchar;
  1255. X            do_space();
  1256. X            continue;
  1257. X        }
  1258. X
  1259. X        /* if we get here, we have done all we can for
  1260. X           this line - now we split the line, or just move
  1261. X           to the next one */
  1262. X        if (okay_char > 0)
  1263. X            curchar = okay_char;            
  1264. X        if (curline == endmark->m_line && curchar >= endmark->m_char)
  1265. X            goto outahere;
  1266. X        /* can't fit in small margin, so we do the best we can */
  1267. X        if (eolp()) {
  1268. X            line_move(FORWARD, NO);
  1269. X            n_indent(indent);
  1270. X        } else {
  1271. X            /* insert a line break - line WAS too long */
  1272. X            DelWtSpace();
  1273. X            LineInsert(1);
  1274. X            if (scrunch && TwoBlank()) {
  1275. X                Eol();
  1276. X                DelNChar();
  1277. X            }
  1278. X            n_indent(indent);
  1279. X        }
  1280. X    }
  1281. Xoutahere:
  1282. X    ToMark(savedot);    /* Back to where we were */
  1283. X    DelMark(endmark);    /* Free up marks */
  1284. X    DelMark(savedot);
  1285. X    this_cmd = last_cmd = 0; /* So everything is under control */
  1286. X    f_mess("");
  1287. X}
  1288. X
  1289. Xextern Line    *para_head,
  1290. X        *para_tail;
  1291. X
  1292. XDoPara(dir)
  1293. X{
  1294. X    register int    num = exp,
  1295. X            first_time = TRUE;    
  1296. X
  1297. X    while (--num >= 0) {
  1298. Xtryagain:    find_para(dir);        /* find paragraph bounderies */
  1299. X        if ((dir == BACKWARD) &&
  1300. X            ((!first_time) || ((para_head == curline) && bolp()))) {
  1301. X                if (bobp())
  1302. X                    complain((char *) 0);
  1303. X            BackChar();
  1304. X            first_time = !first_time;
  1305. X            goto tryagain;
  1306. X        }
  1307. X        SetLine((dir == BACKWARD) ? para_head : para_tail);
  1308. X        if (dir == BACKWARD && !firstp(curline) &&
  1309. X            i_blank(curline->l_prev))
  1310. X            line_move(BACKWARD, NO);
  1311. X        else if (dir == FORWARD) {
  1312. X            if (lastp(curline)) {
  1313. X                Eol();
  1314. X                break;
  1315. X            }
  1316. X            /* otherwise */
  1317. X            line_move(FORWARD, NO);
  1318. X        }
  1319. X    }
  1320. X}
  1321. X
  1322. XBackPara()
  1323. X{
  1324. X    DoPara(BACKWARD);
  1325. X}
  1326. X
  1327. XForPara()
  1328. X{
  1329. X    DoPara(FORWARD);
  1330. X}
  1331. @//E*O*F paragraph.c//
  1332. if test 13888 -ne "`wc -c <'paragraph.c'`"; then
  1333.     echo shar: error transmitting "'paragraph.c'" '(should have been 13888 characters)'
  1334. fi
  1335. fi # end of overwriting check
  1336. echo shar: extracting "'portsrv.c'" '(3209 characters)'
  1337. if test -f 'portsrv.c' ; then 
  1338.   echo shar: will not over-write existing file "'portsrv.c'"
  1339. else
  1340. sed 's/^X//' >portsrv.c <<'@//E*O*F portsrv.c//'
  1341. X/************************************************************************
  1342. X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
  1343. X * provided to you without charge, and with no warranty.  You may give  *
  1344. X * away copies of JOVE, including sources, provided that this notice is *
  1345. X * included in all the files.                                           *
  1346. X ************************************************************************/
  1347. X
  1348. X/* This is a server for jove sub processes.  It runs the command and
  1349. X   signals jove when there is some output ready to send to jove. By the
  1350. X   time we get here, out standard output goes to jove's process input. */
  1351. X
  1352. X#include "tune.h"
  1353. X
  1354. X#ifdef PIPEPROCS    /* the whole file! */
  1355. X
  1356. X#include "jove.h"
  1357. X
  1358. X#include <signal.h>
  1359. X#include <sys/ioctl.h>
  1360. X#ifdef BSD4_2
  1361. X#   include <sys/wait.h>
  1362. X#else
  1363. X#   include <wait.h>
  1364. X#endif
  1365. X
  1366. Xstruct header {
  1367. X    int    pid;
  1368. X    int    nbytes;
  1369. X    char    buf[512];
  1370. X} header;
  1371. X
  1372. X#define HEADSIZE    ((sizeof header.pid) + sizeof (header.nbytes))
  1373. X
  1374. Xerror(str)
  1375. Xchar    *str;
  1376. X{
  1377. X    header.pid = getpid();
  1378. X    header.nbytes = strlen(str);
  1379. X    strcpy(header.buf, str);
  1380. X    proc_write(&header, header.nbytes + 8);
  1381. X    exit(-2);
  1382. X}
  1383. X
  1384. Xint    ppid,
  1385. X    InputFD,
  1386. X    JovesInput;
  1387. X
  1388. Xp_inform()
  1389. X{
  1390. X    long    nbytes;
  1391. X
  1392. X    ioctl(JovesInput, FIONREAD, (char *) &nbytes);
  1393. X    if (nbytes > 0)
  1394. X        kill(ppid, INPUT_SIG);
  1395. X}
  1396. X
  1397. Xproc_write(ptr, n)
  1398. Xchar    *ptr;
  1399. X{
  1400. X    long    nbytes;
  1401. X
  1402. X    ioctl(1, FIONREAD, (char *) &nbytes);
  1403. X    
  1404. X    if (nbytes == 0)
  1405. X        kill(ppid, INPUT_SIG);
  1406. X
  1407. X    (void) write(1, ptr, n);
  1408. X    alarm(1);
  1409. X}
  1410. X
  1411. Xread_pipe()
  1412. X{
  1413. X    register int    n;
  1414. X    
  1415. X    (void) signal(SIGALRM, p_inform);
  1416. X
  1417. X    while ((header.nbytes = read(InputFD, header.buf, sizeof header.buf)) > 0) {
  1418. X        n = HEADSIZE + header.nbytes;
  1419. X        proc_write(&header, n);
  1420. X    }
  1421. X}
  1422. X
  1423. X/* ARGSUSED */
  1424. Xmain(argc, argv)
  1425. Xchar    *argv[];
  1426. X{
  1427. X    int    p[2];
  1428. X    int    pid;
  1429. X
  1430. X    if (pipe(p) == -1)
  1431. X        error("Cannot pipe jove portsrv.\n");
  1432. X
  1433. X    ppid = getppid();
  1434. X    switch (pid = fork()) {
  1435. X    case -1:
  1436. X        error("portsrv: cannot fork.\n");
  1437. X
  1438. X    case 0:
  1439. X        /* We'll intercept childs output in p[0] */
  1440. X        (void) dup2(p[1], 1);
  1441. X        (void) dup2(p[1], 2);
  1442. X        (void) close(p[0]);
  1443. X        (void) close(p[1]);
  1444. X            
  1445. X        (void) setpgrp(getpid(), getpid());
  1446. X        execv(argv[2], &argv[3]);
  1447. X        _exit(-4);
  1448. X
  1449. X    default:
  1450. X        (void) close(0);
  1451. X                /* Don't want this guy to read anything
  1452. X                   jove sends to our soon to be created
  1453. X                   child */
  1454. X
  1455. X        JovesInput = atoi(argv[1]);
  1456. X        (void) signal(SIGINT, SIG_IGN);
  1457. X        (void) signal(SIGQUIT, SIG_IGN);
  1458. X        (void) close(p[1]);
  1459. X
  1460. X        /* Tell jove the pid of the real child as opposed to us. */
  1461. X        header.pid = getpid();
  1462. X        header.nbytes = sizeof (int);
  1463. X        *(int *) header.buf = pid;
  1464. X        (void) write(1, (char *) &header, sizeof pid + HEADSIZE);
  1465. X        p_inform();    /* Inform jove */
  1466. X
  1467. X        /* Read proc's output and send it to jove */
  1468. X        InputFD = p[0];
  1469. X        read_pipe();
  1470. X        (void) close(p[0]);
  1471. X        header.pid = getpid();
  1472. X        header.nbytes = EOF;    /* Tell jove we are finished */
  1473. X        (void) write(1, (char *) &header, HEADSIZE);
  1474. X        p_inform();
  1475. X        /* Try to exit like our child did ... */
  1476. X        {
  1477. X            union wait    w;
  1478. X
  1479. X#ifndef VMUNIX
  1480. X            while (wait2(&w.w_status, 0) != pid)
  1481. X#else
  1482. X            while (wait3(&w.w_status, 0, 0) != pid)
  1483. X#endif
  1484. X                ;
  1485. X            if (WIFEXITED(w))
  1486. X                exit(w.w_retcode);
  1487. X            else if (WIFSIGNALED(w))
  1488. X                kill(getpid(), w.w_termsig);
  1489. X        }
  1490. X    }
  1491. X}
  1492. X
  1493. X#else PIPEPROCS
  1494. Xmain()
  1495. X{
  1496. X}
  1497. X#endif
  1498. @//E*O*F portsrv.c//
  1499. if test 3209 -ne "`wc -c <'portsrv.c'`"; then
  1500.     echo shar: error transmitting "'portsrv.c'" '(should have been 3209 characters)'
  1501. fi
  1502. fi # end of overwriting check
  1503. echo shar: extracting "'proc.c'" '(14390 characters)'
  1504. if test -f 'proc.c' ; then 
  1505.   echo shar: will not over-write existing file "'proc.c'"
  1506. else
  1507. sed 's/^X//' >proc.c <<'@//E*O*F proc.c//'
  1508. X/************************************************************************
  1509. X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
  1510. X * provided to you without charge, and with no warranty.  You may give  *
  1511. X * away copies of JOVE, including sources, provided that this notice is *
  1512. X * included in all the files.                                           *
  1513. X ************************************************************************/
  1514. X
  1515. X#include "jove.h"
  1516. X#include "io.h"
  1517. X#include "termcap.h"
  1518. X
  1519. X#include <signal.h>
  1520. X#include <varargs.h>
  1521. X
  1522. X/* This disgusting RE search string parses output from the GREP
  1523. X   family, from the pdp11 compiler, pcc, and lint.  Jay (HACK)
  1524. X   Fenlasen changed this to work for the lint errors. */
  1525. Xprivate char
  1526. X    *errfmt = "^\\{\",\\}\\([^:\"( \t]*\\)\\{\"\\, line ,:,(\\} *\\([0-9][0-9]*\\)[:)]\
  1527. X\\|::  *\\([^(]*\\)(\\([0-9]*\\))$\
  1528. X\\|( \\([^(]*\\)(\\([0-9]*\\)) ),";
  1529. X
  1530. Xstruct error {
  1531. X    Buffer        *er_buf;    /* Buffer error is in */
  1532. X    Line        *er_mess,    /* Actual error message */
  1533. X            *er_text;    /* Actual error */
  1534. X    int        er_char;    /* char pos of error */
  1535. X    struct error    *er_prev,    /* List of errors */
  1536. X            *er_next;
  1537. X};
  1538. X
  1539. Xstruct error    *cur_error = 0,
  1540. X        *errorlist = 0;
  1541. XBuffer        *perr_buf = 0;    /* Buffer with error messages */
  1542. X
  1543. Xint    WtOnMk = 1;        /* Write the modified files when we make */
  1544. X
  1545. X/* Add an error to the end of the list of errors.  This is used for
  1546. X   parse-{C,LINT}-errors and for the spell-buffer command */
  1547. X
  1548. Xprivate struct error *
  1549. XAddError(laste, errline, buf, line, charpos)
  1550. Xstruct error    *laste;
  1551. XLine    *errline,
  1552. X    *line;
  1553. XBuffer    *buf;
  1554. X{
  1555. X    struct error    *new = (struct error *) emalloc(sizeof *new);
  1556. X
  1557. X    new->er_prev = laste;
  1558. X    if (laste)
  1559. X        laste->er_next = new;
  1560. X    else {
  1561. X        if (errorlist)        /* Free up old errors */
  1562. X            ErrFree();
  1563. X        cur_error = errorlist = new;
  1564. X    }
  1565. X    laste = new;
  1566. X    new->er_next = 0;
  1567. X    new->er_buf = buf;
  1568. X    new->er_text = line;
  1569. X    new->er_char = charpos;
  1570. X    new->er_mess = errline;
  1571. X
  1572. X    return new;
  1573. X}
  1574. X
  1575. XParseAll()
  1576. X{
  1577. X    ErrParse(errfmt);
  1578. X}
  1579. X
  1580. XXParse()
  1581. X{
  1582. X    char    *sstr;
  1583. X
  1584. X    sstr = ask(errfmt, ProcFmt);
  1585. X    ErrParse(sstr);
  1586. X}
  1587. X
  1588. X/* Parse for {C,LINT} errors (or anything that matches fmtstr) in the
  1589. X   current buffer.  Set up for the next-error command.  This is neat
  1590. X   because this will work for any kind of output that prints a file
  1591. X   name and a line number on the same line. */
  1592. X
  1593. XErrParse(fmtstr)
  1594. Xchar    *fmtstr;
  1595. X{
  1596. X    Bufpos    *bp;
  1597. X    char    fname[FILESIZE],
  1598. X        lineno[10],
  1599. X        REbuf[256],
  1600. X        *REalts[10];
  1601. X    int    lnum,
  1602. X        last_lnum = -1;
  1603. X    struct error    *ep = 0;
  1604. X    Buffer    *buf,
  1605. X        *lastb = 0;
  1606. X    Line    *err_line;    
  1607. X
  1608. X    ErrFree();        /* This is important! */
  1609. X    ToFirst();
  1610. X    perr_buf = curbuf;
  1611. X    REcompile(fmtstr, 1, REbuf, REalts);
  1612. X    /* Find a line with a number on it. */
  1613. X    while (bp = docompiled(FORWARD, REbuf, REalts)) {
  1614. X        SetDot(bp);
  1615. X        putmatch(1, fname, sizeof fname);
  1616. X        putmatch(2, lineno, sizeof lineno);
  1617. X        buf = do_find((Window *) 0, fname, 1);
  1618. X        if (buf != lastb) {
  1619. X            lastb = buf;
  1620. X            last_lnum = -1;        /* signals new file */
  1621. X            err_line = buf->b_first;
  1622. X        }
  1623. X        lnum = chr_to_int(lineno, 10, 0);
  1624. X        if (lnum == last_lnum)    /* one error per line is nicer */
  1625. X            continue;
  1626. X        if (last_lnum == -1)
  1627. X            last_lnum = 1;    /* that's where we really are */
  1628. X        err_line = next_line(err_line, lnum - last_lnum);
  1629. X        ep = AddError(ep, curline, buf, err_line, 0);
  1630. X        last_lnum = lnum;
  1631. X    }
  1632. X    if (cur_error != 0)
  1633. X        ShowErr();
  1634. X    exp = 1;
  1635. X}
  1636. X
  1637. X/* Free up all the errors */
  1638. X
  1639. XErrFree()
  1640. X{
  1641. X    register struct error    *ep;
  1642. X
  1643. X    for (ep = errorlist; ep != 0; ep = ep->er_next)
  1644. X        free((char *) ep);
  1645. X    errorlist = cur_error = 0;
  1646. X}
  1647. X
  1648. X/* Internal next error sets cur_error to the next error, taking the
  1649. X   argument count, supplied by the user, into consideration. */
  1650. X
  1651. Xprivate char    errbounds[] = "You're at the %s error.",
  1652. X        noerrs[] = "No errors!";
  1653. X
  1654. Xprivate
  1655. Xtoerror(forward)
  1656. X{
  1657. X    register int    i;
  1658. X    register struct error    *e = cur_error;
  1659. X
  1660. X    if (e == 0)
  1661. X        complain(noerrs);
  1662. X    if ((forward && (e->er_next == 0)) ||
  1663. X        (!forward && (e->er_prev == 0)))
  1664. X        complain(errbounds, forward ? "last" : "first");
  1665. X
  1666. X    for (i = 0; i < exp; i++) {
  1667. X        if ((e = forward ? e->er_next : e->er_prev) == 0)
  1668. X            break;
  1669. X        cur_error = e;
  1670. X    }
  1671. X}
  1672. X
  1673. XNextError()
  1674. X{
  1675. X    ToError(1);
  1676. X}
  1677. X
  1678. XPrevError()
  1679. X{
  1680. X    ToError(0);
  1681. X}
  1682. X
  1683. Xprivate
  1684. Xokay_error()
  1685. X{
  1686. X    return ((inlist(perr_buf->b_first, cur_error->er_mess)) &&
  1687. X        (inlist(cur_error->er_buf->b_first, cur_error->er_text)));
  1688. X}
  1689. X
  1690. X/* Go the the next error, if there is one.  Put the error buffer in
  1691. X   one window and the buffer with the error in another window.
  1692. X   It checks to make sure that the error actually exists. */
  1693. X
  1694. XToError(forward)
  1695. X{
  1696. X    do {
  1697. X        toerror(forward);
  1698. X        exp = 1;
  1699. X    } while (!okay_error());
  1700. X    ShowErr();
  1701. X}
  1702. X
  1703. Xint    EWSize = 20;    /* percentage of screen the error window
  1704. X               should be */
  1705. X
  1706. Xset_wsize(wsize)
  1707. Xint    wsize;
  1708. X{
  1709. X    wsize = (LI * wsize) / 100;
  1710. X    if (wsize >= 1 && !one_windp())
  1711. X        WindSize(curwind, wsize - (curwind->w_height - 1));
  1712. X}
  1713. X
  1714. X/* Show the current error, i.e. put the line containing the error message
  1715. X   in one window, and the buffer containing the actual error in another
  1716. X   window. */
  1717. X
  1718. XShowErr()
  1719. X{
  1720. X    Window    *err_wind,
  1721. X        *buf_wind;
  1722. X
  1723. X    if (cur_error == 0)
  1724. X        complain(noerrs);
  1725. X    if (!okay_error()) {
  1726. X        rbell();
  1727. X        return;
  1728. X    }
  1729. X    err_wind = windbp(perr_buf);
  1730. X    buf_wind = windbp(cur_error->er_buf);
  1731. X
  1732. X    if (err_wind && !buf_wind) {
  1733. X        SetWind(err_wind);
  1734. X        pop_wind(cur_error->er_buf->b_name, NO, -1);
  1735. X        buf_wind = curwind;
  1736. X    } else if (!err_wind && buf_wind) {
  1737. X        SetWind(buf_wind);
  1738. X        pop_wind(perr_buf->b_name, NO, -1);
  1739. X        err_wind = curwind;
  1740. X    } else if (!err_wind && !buf_wind) {
  1741. X        pop_wind(perr_buf->b_name, NO, -1);
  1742. X        err_wind = curwind;
  1743. X        pop_wind(cur_error->er_buf->b_name, NO, -1);
  1744. X        buf_wind = curwind;
  1745. X    }
  1746. X
  1747. X    /* Put the current error message at the top of its Window */
  1748. X    SetWind(err_wind);
  1749. X    SetLine(cur_error->er_mess);
  1750. X    SetTop(curwind, (curwind->w_line = cur_error->er_mess));
  1751. X    set_wsize(EWSize);
  1752. X
  1753. X    /* now go to the the line with the error in the other window */
  1754. X    SetWind(buf_wind);
  1755. X    DotTo(cur_error->er_text, cur_error->er_char);
  1756. X}
  1757. X
  1758. Xchar    ShcomBuf[128] = {0};
  1759. X
  1760. X/* Make a buffer name given the command `command', i.e. "fgrep -n foo *.c"
  1761. X   will return the buffer name "fgrep".  */
  1762. X
  1763. Xchar *
  1764. XMakeName(command)
  1765. Xchar    *command;
  1766. X{
  1767. X    static char    bufname[50];
  1768. X    register char    *cp = bufname,
  1769. X            c;
  1770. X
  1771. X    while ((c = *command++) && (c == ' ' || c == '\t'))
  1772. X        ;
  1773. X    do
  1774. X        *cp++ = c;
  1775. X    while ((c = *command++) && (c != ' ' && c != '\t'));
  1776. X    *cp = 0;
  1777. X    strcpy(bufname, basename(bufname));
  1778. X
  1779. X    return bufname;
  1780. X}
  1781. X
  1782. X/* Run make, first writing all the modified buffers (if the WtOnMk flag is
  1783. X   non-zero), parse the errors, and go the first error. */
  1784. X
  1785. Xchar    make_cmd[128] = "make";
  1786. X
  1787. XMakeErrors()
  1788. X{
  1789. X    Window    *old = curwind;
  1790. X    int    status,
  1791. X        compilation;
  1792. X    
  1793. X    if (WtOnMk)
  1794. X        put_bufs(0);
  1795. X    /* When we're not doing make or cc (i.e., the last command
  1796. X       was probably a grep or something) and the user just types
  1797. X       C-X C-E, he probably (possibly, hopefully, usually (in my
  1798. X       case)) doesn't want to do the grep again but rather wants
  1799. X       to do a make again; so we ring the bell and insert the
  1800. X       default command and let the person decide. */
  1801. X
  1802. X    compilation = (sindex("make", make_cmd) || sindex("cc", make_cmd));
  1803. X    if (exp_p || !compilation) {
  1804. X        if (!compilation) {
  1805. X            rbell();
  1806. X            Inputp = make_cmd;    /* insert the default for the
  1807. X                           user */
  1808. X        }
  1809. X        null_ncpy(make_cmd, ask(make_cmd, "Compilation command: "),
  1810. X                sizeof (make_cmd) - 1);
  1811. X    }
  1812. X    status = UnixToBuf(MakeName(make_cmd), YES, EWSize, YES, Shell, ShFlags, make_cmd, (char *) 0);
  1813. X    com_finish(status, make_cmd);
  1814. X
  1815. X    ErrParse(errfmt);
  1816. X
  1817. X    if (!cur_error)
  1818. X        SetWind(old);
  1819. X}
  1820. X
  1821. X#ifdef SPELL
  1822. X
  1823. XSpelBuffer()
  1824. X{
  1825. X    char    *Spell = "Spell",
  1826. X        com[100];
  1827. X    Window    *savewp = curwind;
  1828. X
  1829. X    put_bufs(0);
  1830. X    sprintf(com, "spell %s", curbuf->b_fname);
  1831. X    (void) UnixToBuf(Spell, YES, EWSize, YES, Shell, ShFlags, com, (char *) 0);
  1832. X    message("[Delete the irrelevant words and then type C-X C-C]");
  1833. X    Recur();
  1834. X    SetWind(savewp);
  1835. X    SpelParse(Spell);
  1836. X}
  1837. X
  1838. XSpelWords()
  1839. X{
  1840. X    char    *buftospel;
  1841. X    Buffer    *wordsb = curbuf;
  1842. X
  1843. X    if ((buftospel = ask_buf((Buffer *) 0)) == 0)
  1844. X        return;
  1845. X    SetBuf(do_select(curwind, buftospel));
  1846. X    SpelParse(wordsb->b_name);
  1847. X}
  1848. X
  1849. XSpelParse(bname)
  1850. Xchar    *bname;
  1851. X{
  1852. X    Buffer    *buftospel,
  1853. X        *wordsb;
  1854. X    char    wordspel[100];
  1855. X    Bufpos    *bp;
  1856. X    struct error    *ep = 0;
  1857. X
  1858. X    ErrFree();        /* This is important! */
  1859. X
  1860. X    buftospel = curbuf;
  1861. X    wordsb = buf_exists(bname);
  1862. X    perr_buf = wordsb;    /* This is important (buffer containing
  1863. X                   error messages) */
  1864. X    SetBuf(wordsb);
  1865. X    ToFirst();
  1866. X    f_mess("Finding misspelled words ... ");
  1867. X    while (!lastp(curline)) {
  1868. X        sprintf(wordspel, "\\<%s\\>", linebuf);
  1869. X        SetBuf(buftospel);
  1870. X        ToFirst();
  1871. X        while (bp = dosearch(wordspel, 1, 1)) {
  1872. X            SetDot(bp);
  1873. X            ep = AddError(ep, wordsb->b_dot, buftospel,
  1874. X                      curline, curchar);
  1875. X        }
  1876. X        SetBuf(wordsb);
  1877. X        line_move(FORWARD, NO);
  1878. X    }
  1879. X    add_mess("Done.");
  1880. X    SetBuf(buftospel);
  1881. X    ShowErr();
  1882. X}
  1883. X
  1884. X#endif SPELL
  1885. X
  1886. XShToBuf()
  1887. X{
  1888. X    char    bufname[100];
  1889. X
  1890. X    strcpy(bufname, ask((char *) 0, "Buffer: "));
  1891. X    DoShell(bufname, ask(ShcomBuf, "Command: "));
  1892. X}
  1893. X
  1894. XShellCom()
  1895. X{
  1896. X    null_ncpy(ShcomBuf, ask(ShcomBuf, ProcFmt), (sizeof ShcomBuf) - 1);
  1897. X    DoShell(MakeName(ShcomBuf), ShcomBuf);
  1898. X}
  1899. X
  1900. X/* Run the shell command into `bufname'.  Empty the buffer except when we
  1901. X   give a numeric argument, in which case it inserts the output at the
  1902. X   current position in the buffer.  */
  1903. X
  1904. Xprivate
  1905. XDoShell(bufname, command)
  1906. Xchar    *bufname,
  1907. X    *command;
  1908. X{
  1909. X    Window    *savewp = curwind;
  1910. X    int    status;
  1911. X
  1912. X    exp = 1;
  1913. X    status = UnixToBuf(bufname, YES, 0, !exp_p, Shell,
  1914. X               ShFlags, command, (char *) 0);
  1915. X    com_finish(status, command);
  1916. X    SetWind(savewp);
  1917. X}
  1918. X
  1919. Xprivate
  1920. Xcom_finish(status, cmd)
  1921. Xregister int    status;
  1922. Xchar    *cmd;
  1923. X{
  1924. X    s_mess("[%s: ", cmd);
  1925. X    if (status == 0)
  1926. X        add_mess("completed successfully");
  1927. X    else
  1928. X        add_mess("exited (%d)", status);
  1929. X    add_mess("]");
  1930. X}
  1931. X
  1932. Xdowait(pid, status)
  1933. Xint    pid,
  1934. X    *status;
  1935. X{
  1936. X#ifndef IPROCS
  1937. X
  1938. X    int    rpid;
  1939. X
  1940. X    while ((rpid = wait(status)) != pid)
  1941. X        ;
  1942. X#else
  1943. X
  1944. X#ifdef BSD4_2
  1945. X#   include <sys/wait.h>
  1946. X#else
  1947. X#   include <wait.h>
  1948. X#endif
  1949. X
  1950. X    union wait    w;
  1951. X    int    rpid;
  1952. X
  1953. X    for (;;) {
  1954. X#ifndef VMUNIX
  1955. X        rpid = wait2(&w.w_status, 0);
  1956. X#else
  1957. X        rpid = wait3(&w, 0, (struct rusage *) 0);
  1958. X#endif
  1959. X        if (rpid == pid) {
  1960. X            if (status)
  1961. X                *status = w.w_status;
  1962. X            break;
  1963. X        } else
  1964. X            kill_off(rpid, w);
  1965. X    }
  1966. X#endif IPROCS
  1967. X}
  1968. X
  1969. X/* Run the command to bufname, erase the buffer if clobber is non-zero,
  1970. X   and redisplay if disp is non-zero.  Leaves current buffer in `bufname'
  1971. X   and leaves any windows it creates lying around.  It's up to the caller
  1972. X   to fix everything up after we're done.  (Usually there's nothing to
  1973. X   fix up.) */
  1974. X
  1975. X/* VARARGS5 */
  1976. X
  1977. XUnixToBuf(bufname, disp, wsize, clobber, va_alist)
  1978. Xchar    *bufname;
  1979. Xva_dcl
  1980. X{
  1981. X    int    p[2],
  1982. X        pid,
  1983. X        eof,
  1984. X        status;
  1985. X    va_list    ap;
  1986. X    char    *argv[32],
  1987. X        *mess;
  1988. X    File    *fp;
  1989. X    int    (*old_int)();
  1990. X
  1991. X    va_start(ap);
  1992. X    make_argv(argv, ap);
  1993. X    va_end(ap);
  1994. X    if (clobber)
  1995. X        isprocbuf(bufname);
  1996. X    if (disp) {
  1997. X        message("Starting up...");
  1998. X        pop_wind(bufname, clobber, clobber ? B_PROCESS : B_FILE);
  1999. X        set_wsize(wsize);
  2000. X        redisplay();
  2001. X    }
  2002. X    /* Now I will attempt to describe how I deal with signals during
  2003. X       the execution of the shell command.  My desire was to be able
  2004. X       to interrupt the shell command AS SOON AS the window pops up.
  2005. X       So, if we have JOB_CONTROL (i.e., the new signal mechanism) I
  2006. X       hold SIGINT, meaning if we interrupt now, we will eventually
  2007. X       see the interrupt, but not before we are ready for it.  We
  2008. X       fork, the child releases the interrupt, it then sees the
  2009. X       interrupt, and so exits.  Meanwhile the parent ignores the
  2010. X       signal, so if there was a pending one, it's now lost.
  2011. X
  2012. X       With no JOB_CONTROL, the best behavior you can expect is, when
  2013. X       you type ^] too very quickly after the window pops up, it may
  2014. X       be ignored.  The behavior BEFORE was that it would interrupt
  2015. X       JOVE and then you would have to continue JOVE and wait a
  2016. X       little while longer before trying again.  Now that is fixed,
  2017. X       in that you just have to type it twice. */
  2018. X
  2019. X#ifdef IPROCS
  2020. X    sighold(SIGCHLD);
  2021. X#endif
  2022. X#ifdef JOB_CONTROL
  2023. X    sighold(SIGINT);
  2024. X#else
  2025. X    old_int = signal(SIGINT, SIG_IGN),
  2026. X#endif
  2027. X    exp = 1;
  2028. X    dopipe(p);
  2029. X    pid = fork();
  2030. X    if (pid == -1) {
  2031. X        pclose(p);
  2032. X        complain("[Fork failed]");
  2033. X    }
  2034. X    if (pid == 0) {
  2035. X#ifdef IPROCS
  2036. X        sigrelse(SIGCHLD);   /* don't know if this matters */
  2037. X#endif IPROCS
  2038. X        (void) signal(SIGINT, SIG_DFL);
  2039. X#ifdef JOB_CONTROL
  2040. X        sigrelse(SIGINT);
  2041. X#endif
  2042. X        (void) close(0);
  2043. X        (void) open("/dev/null", 0);
  2044. X        (void) close(1);
  2045. X        (void) close(2);
  2046. X        (void) dup(p[1]);
  2047. X        (void) dup(p[1]);
  2048. X        pclose(p);
  2049. X        execv(argv[0], &argv[1]);
  2050. X        (void) write(1, "Execl failed.\n", 14);
  2051. X        _exit(1);
  2052. X    }
  2053. X#ifdef JOB_CONTROL
  2054. X    old_int = signal(SIGINT, SIG_IGN);
  2055. X#endif    
  2056. X    (void) close(p[1]);
  2057. X    fp = fd_open(argv[1], F_READ, p[0], iobuff, LBSIZE);
  2058. X    do {
  2059. X        inIOread = 1;
  2060. X         eof = f_gets(fp, genbuf, LBSIZE);
  2061. X        inIOread = 0;
  2062. X        ins_str(genbuf, YES);
  2063. X        if (!eof)
  2064. X            LineInsert(1);
  2065. X        if (disp != 0 && fp->f_cnt <= 0) {
  2066. X#ifdef LOAD_AV
  2067. X            {
  2068. X                double    theavg;
  2069. X
  2070. X            get_la(&theavg);
  2071. X            if (theavg < 2.0)
  2072. X                mess = "Screaming along...";
  2073. X            else if (theavg < 5.0)
  2074. X                mess = "Chugging along...";
  2075. X            else
  2076. X                mess = "Crawling along...";
  2077. X            }
  2078. X#else
  2079. X            mess = "Chugging along...";
  2080. X#endif LOAD_AV
  2081. X            message(mess);
  2082. X            redisplay();
  2083. X        }
  2084. X    } while (!eof);
  2085. X    if (disp)
  2086. X        DrawMesg(NO);
  2087. X    close_file(fp);
  2088. X    dowait(pid, &status);
  2089. X#ifdef JOB_CONTROL
  2090. X    (void) sigrelse(SIGINT);
  2091. X#endif
  2092. X    (void) signal(SIGINT, old_int);
  2093. X#ifdef IPROCS
  2094. X    sigrelse(SIGCHLD);
  2095. X#endif
  2096. X    return status;
  2097. X}
  2098. X
  2099. X#ifdef BSD4_2
  2100. X
  2101. Xprivate int    SigMask = 0;
  2102. X
  2103. Xsighold(sig)
  2104. X{
  2105. X    (void) sigblock(SigMask |= (1 << (sig - 1)));
  2106. X}
  2107. X
  2108. Xsigrelse(sig)
  2109. X{
  2110. X    (void) sigsetmask(SigMask &= ~(1 << (sig - 1)));
  2111. X}
  2112. X
  2113. X#endif
  2114. X
  2115. XFilterRegion()
  2116. X{
  2117. X    char    *cmd = ask((char *) 0, ": %f (through command) ", ProcFmt);
  2118. X
  2119. X    RegToUnix(curbuf, cmd);
  2120. X}
  2121. X
  2122. X/* Send the current region to CMD and insert the output from the
  2123. X   command into OUT_BUF. */
  2124. X
  2125. XRegToUnix(outbuf, cmd)
  2126. XBuffer    *outbuf;
  2127. Xchar    *cmd;
  2128. X{
  2129. X    Mark    *m = CurMark();
  2130. X    char    *tname = mktemp("/tmp/jfilterXXXXXX"),
  2131. X        combuf[130];
  2132. X    Window    *save_wind = curwind;
  2133. X    int    status;
  2134. X    File    *fp;
  2135. X
  2136. X    CATCH
  2137. X    fp = open_file(tname, iobuff, F_WRITE, COMPLAIN, QUIET);
  2138. X    putreg(fp, m->m_line, m->m_char, curline, curchar, YES);
  2139. X    DelReg();
  2140. X    sprintf(combuf, "%s < %s", cmd, tname);
  2141. X    status = UnixToBuf(outbuf->b_name, NO, 0, outbuf->b_type == B_SCRATCH,
  2142. X               Shell, ShFlags, combuf, (char *) 0);
  2143. X    ONERROR
  2144. X    ;    /* Do nothing ... but fall through and delete the tmp
  2145. X           file. */
  2146. X    ENDCATCH
  2147. X    f_close(fp);
  2148. X    (void) unlink(tname);
  2149. X    SetWind(save_wind);
  2150. X    com_finish(status, combuf);
  2151. X}
  2152. X
  2153. Xisprocbuf(bufname)
  2154. Xchar    *bufname;
  2155. X{
  2156. X    Buffer    *bp;
  2157. X
  2158. X    if ((bp = buf_exists(bufname)) != 0 && bp->b_type != B_PROCESS)
  2159. X        confirm("Over-write buffer %s?", bufname);
  2160. X}
  2161. @//E*O*F proc.c//
  2162. if test 14390 -ne "`wc -c <'proc.c'`"; then
  2163.     echo shar: error transmitting "'proc.c'" '(should have been 14390 characters)'
  2164. fi
  2165. fi # end of overwriting check
  2166. echo shar: extracting "'re1.c'" '(9617 characters)'
  2167. if test -f 're1.c' ; then 
  2168.   echo shar: will not over-write existing file "'re1.c'"
  2169. else
  2170. sed 's/^X//' >re1.c <<'@//E*O*F re1.c//'
  2171. X/************************************************************************
  2172. X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
  2173. X * provided to you without charge, and with no warranty.  You may give  *
  2174. X * away copies of JOVE, including sources, provided that this notice is *
  2175. X * included in all the files.                                           *
  2176. X ************************************************************************/
  2177. X
  2178. X#include "jove.h"
  2179. X#include "io.h"
  2180. X#include "re.h"
  2181. X
  2182. Xstatic
  2183. Xsubstitute(query, l1, char1, l2, char2)
  2184. XLine    *l1,
  2185. X    *l2;
  2186. X{
  2187. X    Line    *lp;
  2188. X    int    numdone = 0,
  2189. X        offset = curchar,
  2190. X        stop = 0;
  2191. X    disk_line    UNDO_da = 0;
  2192. X    Line        *UNDO_lp = 0;
  2193. X
  2194. X    lsave();
  2195. X    REdirection = FORWARD;
  2196. X
  2197. X    lp = l1;
  2198. X    for (lp = l1; (lp != l2->l_next) && !stop; lp = lp->l_next) {
  2199. X        offset = (lp == l1) ? char1 : 0;
  2200. X        while (!stop && re_lindex(lp, offset, compbuf, alternates, 0)) {
  2201. X            if (lp == l2 && REeom > char2)    /* nope, leave this alone */
  2202. X                break;
  2203. X            DotTo(lp, REeom);
  2204. X            offset = curchar;
  2205. X            if (query) {
  2206. X                message("Replace (Type '?' for help)? ");
  2207. Xreswitch:            redisplay();
  2208. X                switch (Upper(getchar())) {
  2209. X                case '.':
  2210. X                    stop++;
  2211. X                    /* Fall into ... */
  2212. X
  2213. X                case ' ':
  2214. X                case 'Y':
  2215. X                    break;
  2216. X
  2217. X                case BS:
  2218. X                case RUBOUT:
  2219. X                case 'N':
  2220. X                    if (linebuf[offset++] == '\0')
  2221. X                        goto nxtline;
  2222. X                    continue;
  2223. X
  2224. X                case CTL(W):
  2225. X                    re_dosub(linebuf, YES);
  2226. X                    numdone++;
  2227. X                    offset = curchar = REbom;
  2228. X                    makedirty(curline);
  2229. X                    /* Fall into ... */
  2230. X
  2231. X                case CTL(R):
  2232. X                case 'R':
  2233. X                    RErecur();
  2234. X                    offset = curchar;
  2235. X                    lp = curline;
  2236. X                    continue;
  2237. X
  2238. X                case CTL(U):
  2239. X                case 'U':
  2240. X                    if (UNDO_lp == 0)
  2241. X                        continue;
  2242. X                    lp = UNDO_lp;
  2243. X                    lp->l_dline = UNDO_da | DIRTY;
  2244. X                    offset = 0;
  2245. X                    numdone--;
  2246. X                    continue;
  2247. X
  2248. X                case 'P':
  2249. X                case '!':
  2250. X                    query = 0;
  2251. X                    break;
  2252. X
  2253. X                case CR:
  2254. X                case LF:
  2255. X                case 'Q':
  2256. X                    goto done;
  2257. X
  2258. X                case CTL(L):
  2259. X                    RedrawDisplay();
  2260. X                    goto reswitch;
  2261. X
  2262. X                default:
  2263. X                    rbell();
  2264. Xmessage("Space or Y, Period, Rubout or N, C-R or R, C-W, C-U or U, P or !, Return.");
  2265. X                    goto reswitch;
  2266. X                }
  2267. X            }
  2268. X            re_dosub(linebuf, NO);
  2269. X            numdone++;
  2270. X            modify();
  2271. X            offset = curchar = REeom;
  2272. X            makedirty(curline);
  2273. X            if (query) {
  2274. X                message(mesgbuf);    /* No blinking. */
  2275. X                redisplay();        /* Show the change. */
  2276. X            }
  2277. X            UNDO_da = curline->l_dline;
  2278. X            UNDO_lp = curline;
  2279. X            if (linebuf[offset] == 0)
  2280. Xnxtline:            break;
  2281. X        }
  2282. X    }
  2283. X    SetMark();
  2284. Xdone:    s_mess("%d substitution%n.", numdone, numdone);
  2285. X}
  2286. X
  2287. X/* Prompt for search and replacement strings and do the substitution.  The
  2288. X   point is restored when we're done. */
  2289. X
  2290. Xstatic
  2291. Xreplace(query, inreg)
  2292. X{
  2293. X    Mark    *save = MakeMark(curline, curchar, FLOATER),
  2294. X        *m;
  2295. X    char    *rep_ptr;
  2296. X    Line    *l1 = curline,
  2297. X        *l2 = curbuf->b_last;
  2298. X    int    char1 = curchar,
  2299. X        char2 = length(curbuf->b_last);
  2300. X
  2301. X    if (inreg) {
  2302. X        m = CurMark();
  2303. X        l2 = m->m_line;
  2304. X        char2 = m->m_char;
  2305. X        (void) fixorder(&l1, &char1, &l2, &char2);
  2306. X    }
  2307. X
  2308. X    /* Get search string. */
  2309. X    strcpy(rep_search, ask(rep_search[0] ? rep_search : (char *) 0, ProcFmt));
  2310. X    REcompile(rep_search, UseRE, compbuf, alternates);
  2311. X    /* Now the replacement string.  Do_ask() so the user can play with
  2312. X       the default (previous) replacement string by typing C-R in ask(),
  2313. X       OR, he can just hit Return to replace with nothing. */
  2314. X    rep_ptr = do_ask("\r\n", (int (*)()) 0, rep_str, ": %f %s with ", rep_search);
  2315. X    if (rep_ptr == 0)
  2316. X        rep_ptr = NullStr;
  2317. X    strcpy(rep_str, rep_ptr);
  2318. X
  2319. X    substitute(query, l1, char1, l2, char2);
  2320. X    ToMark(save);
  2321. X    DelMark(save);
  2322. X}
  2323. X
  2324. XRegReplace()
  2325. X{
  2326. X    replace(0, YES);
  2327. X}
  2328. X
  2329. XQRepSearch()
  2330. X{
  2331. X    replace(1, NO);
  2332. X}
  2333. X
  2334. XRepSearch()
  2335. X{
  2336. X    replace(0, NO);
  2337. X}
  2338. X
  2339. X/* C tags package. */
  2340. X
  2341. Xstatic
  2342. Xlookup(searchbuf, filebuf, tag, file)
  2343. Xchar    *searchbuf,
  2344. X    *filebuf,
  2345. X    *tag,
  2346. X    *file;
  2347. X{
  2348. X    register int    taglen = strlen(tag);
  2349. X    char    line[128],
  2350. X        pattern[100];
  2351. X    File    *fp;
  2352. X
  2353. X    fp = open_file(file, iobuff, F_READ, !COMPLAIN, QUIET);
  2354. X    if (fp == NIL)
  2355. X        return 0;
  2356. X    sprintf(pattern, "^%s[^\t]*\t\\([^\t]*\\)\t[?/]\\(.*\\)[?/]$", tag);
  2357. X    while (f_gets(fp, line, sizeof line) != EOF) {
  2358. X        if (line[0] != *tag || strncmp(tag, line, taglen) != 0)
  2359. X            continue;
  2360. X        if (!LookingAt(pattern, line, 0)) {
  2361. X            complain("I thought I saw it!");
  2362. X            break;
  2363. X        } else {
  2364. X            putmatch(2, searchbuf, 100);
  2365. X            putmatch(1, filebuf, 100);
  2366. X            close_file(fp);
  2367. X            return 1;
  2368. X        }
  2369. X    }
  2370. X    f_close(fp);
  2371. X    s_mess("Can't find tag \"%s\".", tag);
  2372. X    return 0;
  2373. X}
  2374. X
  2375. Xchar    TagFile[128] = "./tags";
  2376. X
  2377. Xfind_tag(tag, localp)
  2378. Xchar    *tag;
  2379. X{
  2380. X    char    filebuf[FILESIZE],
  2381. X        sstr[100],
  2382. X        tfbuf[FILESIZE];
  2383. X    register Bufpos    *bp;
  2384. X    register Buffer    *b;
  2385. X    char    *tagfname;
  2386. X
  2387. X    if (!localp) {
  2388. X        char    prompt[128];
  2389. X
  2390. X        sprintf(prompt, "With tag file (%s default): ", TagFile);
  2391. X        tagfname = ask_file(prompt, TagFile, tfbuf);
  2392. X    } else
  2393. X        tagfname = TagFile;
  2394. X    if (lookup(sstr, filebuf, tag, tagfname) == 0)
  2395. X        return;
  2396. X    SetMark();
  2397. X    b = do_find(curwind, filebuf, 0);
  2398. X    if (curbuf != b)
  2399. X        SetABuf(curbuf);
  2400. X    SetBuf(b);
  2401. X    if ((bp = dosearch(sstr, BACKWARD, 0)) == 0 &&
  2402. X        (WrapScan || ((bp = dosearch(sstr, FORWARD, 0)) == 0)))
  2403. X        message("Well, I found the file, but the tag is missing.");
  2404. X    else
  2405. X        SetDot(bp);
  2406. X}
  2407. X
  2408. XFindTag()
  2409. X{
  2410. X    int    localp = !exp_p;
  2411. X    char    tag[128];
  2412. X
  2413. X    strcpy(tag, ask((char *) 0, ProcFmt));
  2414. X    find_tag(tag, localp);
  2415. X}
  2416. X
  2417. X/* Find Tag at Dot. */
  2418. X
  2419. XFDotTag()
  2420. X{
  2421. X    int    c1 = curchar,
  2422. X        c2 = c1;
  2423. X    char    tagname[50];
  2424. X
  2425. X    if (!ismword(linebuf[curchar]))
  2426. X        complain("Not a tag!");
  2427. X    while (c1 > 0 && ismword(linebuf[c1 - 1]))
  2428. X        c1--;
  2429. X    while (ismword(linebuf[c2]))
  2430. X        c2++;
  2431. X
  2432. X    null_ncpy(tagname, linebuf + c1, c2 - c1);
  2433. X    find_tag(tagname, !exp_p);
  2434. X}
  2435. X
  2436. X/* I-search returns a code saying what to do:
  2437. X   STOP:    We found the match, so unwind the stack and leave
  2438. X        where it is.
  2439. X   DELETE:    Rubout the last command.
  2440. X   BACKUP:    Back up to where the isearch was last NOT failing.
  2441. X
  2442. X   When a character is typed it is appended to the search string, and
  2443. X   then, isearch is called recursively.  When C-S or C-R is typed, isearch
  2444. X   is again called recursively. */
  2445. X
  2446. X#define STOP    1
  2447. X#define DELETE    2
  2448. X#define BACKUP    3
  2449. X#define TOSTART    4
  2450. X
  2451. Xstatic char    ISbuf[128],
  2452. X        *incp = 0;
  2453. Xint    SExitChar = CR;
  2454. X
  2455. X#define cmp_char(a, b)    ((a) == (b) || (CaseIgnore && (Upper(a) == Upper(b))))
  2456. X
  2457. Xstatic Bufpos *
  2458. Xdoisearch(dir, c, failing)
  2459. Xregister int    c,
  2460. X        dir,
  2461. X        failing;
  2462. X{
  2463. X    static Bufpos    buf;
  2464. X    Bufpos    *bp;
  2465. X    extern int    okay_wrap;
  2466. X
  2467. X    if (c == CTL(S) || c == CTL(R))
  2468. X        goto dosrch;
  2469. X
  2470. X    if (failing)
  2471. X        return 0;
  2472. X    DOTsave(&buf);
  2473. X    if (dir == FORWARD) {
  2474. X        if (cmp_char(linebuf[curchar], c)) {
  2475. X            buf.p_char = curchar + 1;
  2476. X            return &buf;
  2477. X        }
  2478. X    } else {
  2479. X        if (look_at(ISbuf))
  2480. X            return &buf;
  2481. X    }
  2482. Xdosrch:    okay_wrap = YES;
  2483. X    if ((bp = dosearch(ISbuf, dir, 0)) == 0)
  2484. X        rbell();    /* ring the first time there's no match */
  2485. X    okay_wrap = NO;
  2486. X    return bp;
  2487. X}
  2488. X
  2489. XIncFSearch()
  2490. X{
  2491. X    IncSearch(FORWARD);
  2492. X}
  2493. X
  2494. XIncRSearch()
  2495. X{
  2496. X    IncSearch(BACKWARD);
  2497. X}
  2498. X
  2499. Xstatic
  2500. XIncSearch(dir)
  2501. X{
  2502. X    Bufpos    save_env;
  2503. X
  2504. X    DOTsave(&save_env);
  2505. X    ISbuf[0] = 0;
  2506. X    incp = ISbuf;
  2507. X    if (isearch(dir, &save_env) == TOSTART)
  2508. X        SetDot(&save_env);
  2509. X    else {
  2510. X        if (LineDist(curline, save_env.p_line) >= MarkThresh)
  2511. X            DoSetMark(save_env.p_line, save_env.p_char);
  2512. X    }
  2513. X    setsearch(ISbuf);
  2514. X}
  2515. X
  2516. X/* Nicely recursive. */
  2517. X
  2518. Xstatic
  2519. Xisearch(dir, bp)
  2520. XBufpos    *bp;
  2521. X{
  2522. X    Bufpos    pushbp;
  2523. X    int    c,
  2524. X        ndir,
  2525. X        failing;
  2526. X    char    *orig_incp;
  2527. X
  2528. X    if (bp != 0) {        /* Move to the new position. */
  2529. X        pushbp.p_line = bp->p_line;
  2530. X        pushbp.p_char = bp->p_char;
  2531. X        SetDot(bp);
  2532. X        failing = 0;
  2533. X    } else {
  2534. X        DOTsave(&pushbp);
  2535. X        failing = 1;
  2536. X    }
  2537. X    orig_incp = incp;
  2538. X    ndir = dir;        /* Same direction as when we got here, unless
  2539. X                   we change it with C-S or C-R. */
  2540. X    for (;;) {
  2541. X        SetDot(&pushbp);
  2542. X        message(NullStr);
  2543. X        if (failing)
  2544. X            add_mess("Failing ");
  2545. X        if (dir == BACKWARD)
  2546. X            add_mess("reverse-");
  2547. X        add_mess("I-search: %s", ISbuf);
  2548. X        DrawMesg(NO);
  2549. X        add_mess(NullStr);    /* tell me this is disgusting ... */
  2550. X        c = getch();
  2551. X        if (c == SExitChar)
  2552. X            return STOP;
  2553. X        switch (c) {
  2554. X        case RUBOUT:
  2555. X        case BS:
  2556. X            return DELETE;
  2557. X
  2558. X        case CTL(G):
  2559. X            /* If we're failing, we backup until we're no longer
  2560. X               failing or we've reached the beginning; else, we
  2561. X               just about the search and go back to the start. */
  2562. X            if (failing)
  2563. X                return BACKUP;
  2564. X            return TOSTART;
  2565. X
  2566. X        case CTL(\\):
  2567. X            c = CTL(S);
  2568. X        case CTL(S):
  2569. X        case CTL(R):
  2570. X            /* If this is the first time through and we have a
  2571. X               search string left over from last time, use that
  2572. X               one now. */
  2573. X            if (incp == ISbuf) {
  2574. X                strcpy(ISbuf, getsearch());
  2575. X                incp = &ISbuf[strlen(ISbuf)];
  2576. X            }
  2577. X            ndir = (c == CTL(S)) ? FORWARD : BACKWARD;
  2578. X            /* If we're failing and we're not changing our
  2579. X               direction, don't recur since there's no way
  2580. X               the search can work. */
  2581. X            if (failing && ndir == dir) {
  2582. X                rbell();
  2583. X                continue;
  2584. X            }
  2585. X            break;
  2586. X
  2587. X        case '\\':
  2588. X            if (incp > &ISbuf[(sizeof ISbuf) - 1]) {
  2589. X                rbell();
  2590. X                continue;
  2591. X            }
  2592. X            *incp++ = '\\';
  2593. X            add_mess("\\");
  2594. X            /* Fall into ... */
  2595. X
  2596. X        case CTL(Q):
  2597. X        case CTL(^):
  2598. X            add_mess("");
  2599. X            c = getch() | 0400;
  2600. X            /* Fall into ... */
  2601. X
  2602. X        default:
  2603. X            if (c & 0400)
  2604. X                c &= 0177;
  2605. X            else {
  2606. X                if (c > RUBOUT || (c < ' ' && c != '\t')) {
  2607. X                    Ungetc(c);
  2608. X                    return STOP;
  2609. X                }
  2610. X            }
  2611. X            if (incp > &ISbuf[(sizeof ISbuf) - 1]) {
  2612. X                rbell();
  2613. X                continue;
  2614. X            }
  2615. X            *incp++ = c;
  2616. X            *incp = 0;
  2617. X            break;
  2618. X        }
  2619. X        add_mess("%s", orig_incp);
  2620. X        add_mess(" ...");    /* so we know what's going on */
  2621. X        DrawMesg(NO);        /* do it now */
  2622. X        switch (isearch(ndir, doisearch(ndir, c, failing))) {
  2623. X        case TOSTART:
  2624. X            return TOSTART;
  2625. X
  2626. X        case STOP:
  2627. X            return STOP;
  2628. X
  2629. X        case BACKUP:
  2630. X            /* If we're not failing, we just continue to to the
  2631. X               for loop; otherwise we keep returning to the 
  2632. X               previous levels until we find one that isn't
  2633. X               failing OR we reach the beginning. */
  2634. X            if (failing)
  2635. X                return BACKUP;
  2636. X            /* Fall into ... */
  2637. X
  2638. X        case DELETE:
  2639. X            incp = orig_incp;
  2640. X            *incp = 0;
  2641. X            continue;
  2642. X        }
  2643. X    }
  2644. X}
  2645. @//E*O*F re1.c//
  2646. if test 9617 -ne "`wc -c <'re1.c'`"; then
  2647.     echo shar: error transmitting "'re1.c'" '(should have been 9617 characters)'
  2648. fi
  2649. fi # end of overwriting check
  2650. echo shar: extracting "'table.h'" '(870 characters)'
  2651. if test -f 'table.h' ; then 
  2652.   echo shar: will not over-write existing file "'table.h'"
  2653. else
  2654. sed 's/^X//' >table.h <<'@//E*O*F table.h//'
  2655. X/************************************************************************
  2656. X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
  2657. X * provided to you without charge, and with no warranty.  You may give  *
  2658. X * away copies of JOVE, including sources, provided that this notice is *
  2659. X * included in all the files.                                           *
  2660. X ************************************************************************/
  2661. X
  2662. Xtypedef struct word    Word;
  2663. Xtypedef struct table    Table;
  2664. X
  2665. Xstruct word {
  2666. X    Word    *wd_next;
  2667. X    char    *wd_text;
  2668. X};
  2669. X
  2670. Xstruct table {
  2671. X    Table    *t_next;
  2672. X    Word    *t_wordlist;
  2673. X};
  2674. X
  2675. Xextern Table    *make_table();
  2676. Xextern Word    *word_in_table();
  2677. X
  2678. X#define    table_top(table)    (table->t_wordlist)
  2679. X#define next_word(w)        (w->wd_next)
  2680. X#define last_word_p(w)        (w->wd_next == NIL)
  2681. X#define word_text(w)        (w->wd_text)
  2682. X#define word_length(w)        (strlen(word_text(w)))
  2683. @//E*O*F table.h//
  2684. if test 870 -ne "`wc -c <'table.h'`"; then
  2685.     echo shar: error transmitting "'table.h'" '(should have been 870 characters)'
  2686. fi
  2687. fi # end of overwriting check
  2688. echo shar: "End of archive 6 (of 13)."
  2689. cp /dev/null ark6isdone
  2690. DONE=true
  2691. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13; do
  2692.     if test -f ark${I}isdone; then
  2693.         echo "You have run archive ${I}."
  2694.     else
  2695.         echo "You still need to run archive ${I}."
  2696.         DONE=false
  2697.     fi
  2698. done
  2699. case $DONE in
  2700.     true)
  2701.         echo "You have run all 13 archives."
  2702.         echo 'Now read the README and Makefile.'
  2703.         ;;
  2704. esac
  2705. ##  End of shell archive.
  2706. exit 0
  2707.